﻿using System;

namespace RTools_NTS.Util
{
	public class CharBuffer
	{
		public int Length
		{
			get
			{
				return this.tailIndex - this.headIndex;
			}
			set
			{
				this.tailIndex = this.headIndex + value;
				if (this.tailIndex >= this.capacity)
				{
					throw new IndexOutOfRangeException("Tail index greater than capacity");
				}
			}
		}

		public int Capacity
		{
			get
			{
				return this.capacity;
			}
		}

		public CharBuffer()
		{
			this.buffer = new char[this.capacity];
		}

		public CharBuffer(int capacity)
		{
			this.capacity = capacity;
			this.buffer = new char[capacity];
		}

		protected void Grow(int requestedLen)
		{
			int num = Math.Max(this.capacity * 2, requestedLen);
			num = Math.Max(num, 16);
			char[] destinationArray = new char[num];
			Array.Copy(this.buffer, 0, destinationArray, 0, this.capacity);
			this.buffer = destinationArray;
			this.capacity = num;
		}

		protected void CheckCapacity(int requestedLength)
		{
			if (requestedLength + this.headIndex >= this.capacity)
			{
				if (requestedLength + this.headIndex > this.capacity >> 1 && requestedLength < this.capacity - 1)
				{
					this.ShiftToZero();
					return;
				}
				this.Grow(0);
			}
		}

		protected void ShiftToZero()
		{
			int length = this.Length;
			for (int i = 0; i < length; i++)
			{
				this.buffer[i] = this.buffer[i + this.headIndex];
			}
			this.headIndex = 0;
			this.tailIndex = length;
		}

		public void SetBuffer(char[] b, int len)
		{
			this.capacity = b.Length;
			this.buffer = b;
			this.headIndex = 0;
			this.tailIndex = len;
		}

		public void Append(char c)
		{
			if (this.tailIndex >= this.capacity)
			{
				this.CheckCapacity(this.Length + 1);
			}
			char[] array = this.buffer;
			int num = this.tailIndex;
			this.tailIndex = num + 1;
			array[num] = c;
		}

		public void Append(string s)
		{
			if (s.Length + this.tailIndex >= this.capacity)
			{
				this.CheckCapacity(this.Length + s.Length);
			}
			for (int i = 0; i < s.Length; i++)
			{
				char[] array = this.buffer;
				int num = this.tailIndex;
				this.tailIndex = num + 1;
				array[num] = s[i];
			}
		}

		public void Append(CharBuffer s)
		{
			if (s.Length + this.tailIndex >= this.capacity)
			{
				this.CheckCapacity(this.Length + s.Length);
			}
			for (int i = 0; i < s.Length; i++)
			{
				char[] array = this.buffer;
				int num = this.tailIndex;
				this.tailIndex = num + 1;
				array[num] = s[i];
			}
		}

		public void Remove(int i)
		{
			this.Remove(i, 1);
		}

		public void Remove(int i, int n)
		{
			n = Math.Min(n, this.Length);
			if (i == 0)
			{
				this.headIndex += n;
				return;
			}
			Array.Copy(this.buffer, i + this.headIndex + n, this.buffer, i + this.headIndex, this.tailIndex - (i + this.headIndex + n));
		}

		public int IndexOf(char c)
		{
			for (int i = this.headIndex; i < this.tailIndex; i++)
			{
				if (this.buffer[i] == c)
				{
					return i - this.headIndex;
				}
			}
			return -1;
		}

		public void Clear()
		{
			this.headIndex = 0;
			this.tailIndex = 0;
		}

		public char this[int index]
		{
			get
			{
				return this.buffer[index + this.headIndex];
			}
			set
			{
				this.buffer[index + this.headIndex] = value;
			}
		}

		public override string ToString()
		{
			return new string(this.buffer, this.headIndex, this.tailIndex - this.headIndex);
		}

		private int capacity = 128;

		private char[] buffer;

		private int headIndex;

		private int tailIndex;
	}
}
